package com.bigzero.workflow.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bigzero.workflow.common.exception.WorkflowException;
import com.bigzero.workflow.modules.system.constants.SystemCacheConstant;
import com.bigzero.workflow.modules.system.dao.MenuDao;
import com.bigzero.workflow.modules.system.dao.RoleMenuDao;
import com.bigzero.workflow.modules.system.dto.MenuDto;
import com.bigzero.workflow.modules.system.entity.MenuEntity;
import com.bigzero.workflow.modules.system.query.MenuQuery;
import com.bigzero.workflow.modules.system.service.MenuService;
import com.bigzero.workflow.modules.system.vo.MenuVo;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 菜单实现类
 * @Author: fanxinxiong
 * @Date: 2025-02-11 14:48:00
 */
@Service
public class MenuServiceImpl implements MenuService{

    @Resource
    private MenuDao menuDao;
    @Resource
    private RoleMenuDao roleMenuDao;

    /**
     * 根据主键id查询菜单vo
     * @param id 主键id
     * @return MenuVo
     */
    @Cacheable(value = SystemCacheConstant.SYS_MENU_VO_CACHE_EXPIRE, key = "#id", unless = "#result == null ")
    public MenuVo getVoById(String id){
        return menuDao.getVoById(id);
    }

    /**
     * 新增或者修改校验
     *
     * @param menuEntity
     */
    public void insertOrUpdateValidate(MenuEntity menuEntity){
        Date date = new Date();
        if(StringUtils.isNotBlank(menuEntity.getId())){
            MenuEntity dbMenuEntity = menuDao.selectById(menuEntity.getId());
            if(dbMenuEntity == null) {
                throw new WorkflowException("失败:菜单不存在");
            }
        }else{
            menuEntity.setCreateTime(date);
        }
        menuEntity.setUpdateTime(date);
    }

    /**
     * 新增或修改菜单
     * @param menuDto 菜单dto
     * @return int
     */
    @CachePut(value = SystemCacheConstant.SYS_MENU_VO_CACHE_EXPIRE, key = "#result.id")
    public MenuVo insertOrUpdate(MenuDto menuDto){
        MenuEntity menuEntity = new MenuEntity();
        BeanUtils.copyProperties(menuDto, menuEntity);
        //新增或者修改校验
        insertOrUpdateValidate(menuEntity);
        if(StringUtils.isBlank(menuEntity.getId())){
            menuDao.insert(menuEntity);
        }else{
            LambdaUpdateWrapper<MenuEntity> lambdaUpdate = Wrappers.lambdaUpdate();
            lambdaUpdate.eq(MenuEntity :: getId, menuEntity.getId());
            menuDao.update(menuEntity, lambdaUpdate);
        }

        MenuVo menuVo = new MenuVo();
        BeanUtils.copyProperties(menuEntity, menuVo);
        return menuVo;
    }

    /**
     * 根据id删除菜单
     * @param id 主键id
     * @return int
     */
    @CacheEvict(value = SystemCacheConstant.SYS_MENU_VO_CACHE_KEY, key = "#id", allEntries = true)
    public int deleteById(String id){
        MenuVo menuVo = menuDao.getVoById(id);
        if(menuVo == null){
            throw new WorkflowException("失败:菜单不存在");
        }
        LambdaQueryWrapper<MenuEntity> lqw = new QueryWrapper<MenuEntity>().lambda();
        lqw.eq(MenuEntity :: getParentId, id);
        Long childrenMenuCount = menuDao.selectCount(lqw);
        if(childrenMenuCount > 0){
            throw new WorkflowException("失败:请先删除菜单关联的子菜单");
        }
        //根据菜单id删除角色菜单关系
        roleMenuDao.deleteByMenuId(id);
        //根据id删除菜单
        return menuDao.deleteById(id);
    }

    /**
     * 树形表格
     * @param parentId 父id
     * @param query
     * @return List<MenuVo>
     */
    public List<MenuVo> treeTable(String parentId, MenuQuery query){
        List<MenuVo> menuVoList;
        if (StringUtils.isNotBlank(query.getName())) {
            menuVoList = menuDao.selectVoList(query);
        } else {
            List<MenuVo> voList = menuDao.selectVoList(query);
            menuVoList = buildTree(parentId, voList);
        }
        return menuVoList;
    }

    /**
     * 根据集合构建树
     *
     * @param parentId
     * @param menuVoList
     * @return List<MenuVo>
     * @author: fanxinxiong
     * @date: 2024-06-07
     */
    public List<MenuVo> buildTree(String parentId, List<MenuVo> menuVoList) {
        List<MenuVo> treeList = new ArrayList<MenuVo>();
        menuVoList.stream().forEach(vo -> {
            if (parentId.equals(vo.getParentId())) {
                treeList.add(findChild(vo, menuVoList));
            }
        });
        return treeList;
    }

    /**
     * 查找子节点
     *
     * @param menuVo
     * @param menuVoList
     * @return MenuVo
     * @author: fanxinxiong
     * @date: 2024-06-07
     */
    public MenuVo findChild(MenuVo menuVo, List<MenuVo> menuVoList) {
        menuVoList.stream().forEach(v -> {
            if (v.getParentId() != null && v.getParentId().equals(menuVo.getId())) {
                if (menuVo.getChildren() == null) {
                    menuVo.setChildren(new ArrayList<MenuVo>());
                }
                menuVo.getChildren().add(findChild(v, menuVoList));
            }
        });
        return menuVo;
    }

    /**
     * 根据map参数查询vo集合
     * @param map
     * @return List<MenuVo>
     */
    public List<MenuVo> getVoListByMap(HashMap<String, Object> map){
        return menuDao.selectVoListByMap(map);
    }

    /**
     * 菜单下拉树
     * @return List<MenuVo>
     */
    public List<MenuVo> dropdownTree(){
        MenuQuery query = new MenuQuery();
        List<MenuVo> voList = menuDao.selectVoList(query);
        List<MenuVo> menuVoList = buildDropdownTree("0", voList);
        return menuVoList;
    }

    /**
     * 根据集合构建树
     *
     * @param parentId
     * @param menuVoList
     * @return List<MenuVo>
     * @author: fanxinxiong
     * @date: 2024-06-07
     */
    public List<MenuVo> buildDropdownTree(String parentId, List<MenuVo> menuVoList) {
        List<MenuVo> treeList = new ArrayList<MenuVo>();
        menuVoList.stream().forEach(vo -> {
            if(vo != null && (vo.getType() == 4 || vo.getType() == 5 || vo.getType() == 6 || vo.getType() == 7)){
                MenuVo parentVo = getVoById(vo.getParentId());
                vo.setName((parentVo != null ? (parentVo.getName() + "_") : "") + vo.getName());
            }
            if(parentId.equals(vo.getParentId())) {
                treeList.add(findChild(vo, menuVoList));
            }
        });
        return treeList;
    }

    /**
     * 获取父级菜单集合
     * @return List<MenuEntity>
     */
    public List<MenuEntity> getParentMenuList(){
        List<MenuEntity> list = menuDao.getParentMenuList();
        list = Optional.ofNullable(list).orElse(new ArrayList<>());
        MenuEntity rootEntity = new MenuEntity();
        rootEntity.setId("0");
        rootEntity.setName("顶级菜单");
        list.add(0, rootEntity);
        return list;
    }
}
